package ms.jacrim.pddl;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import ms.jacrim.pddl.PddlProblem.PddlPredicate;
import ms.utils.XmlFile;

import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class PddlProblemGenerator {
	private XmlFile config;
	
	public void setConfig(XmlFile config) {
		this.config = config;
	}
	
	public PddlProblem generate() throws Exception {
		PddlProblem result = new PddlProblem();
		XPath xpath = XPathFactory.newInstance().newXPath();

		// Element custom = config.selectSingleNode("//pddl/fact/custom");
		//		
		// if (custom != null) {
		// String customPart = custom.getTextContent().replaceAll("\r", "");
		// for (String s : customPart.split("\n")) {
		// String line = s.trim().replace("\t", "");
		// if (line.length() > 0 && !line.startsWith(";")) {
		// result.addFact(line);
		// }
		// }
		// }
		
		// generate coeffiences
		String sat_coeff = (String) xpath.evaluate("//pddl/fact/@satisfaction_coeff", config.Root, XPathConstants.STRING);
		String eff_coeff = (String) xpath.evaluate("//pddl/fact/@work_load_coeff", config.Root, XPathConstants.STRING);
		
		String metric = config.evalXPath("//pddl/@metric");
		if (metric != null && metric.length() > 0)
			result.setMetric(metric);
		
		result.addFact(String.format("(= (satisfaction_coeff) %s)", sat_coeff));
		result.addFact(String.format("(= (work_load_coeff) %s)", eff_coeff));
		
		result.addObject("foo", "t_gtype");
		
		// generate goals
		NodeList goals = (NodeList) xpath.evaluate("//fact/goals/goal", config.Root, XPathConstants.NODESET);
		for (int i = 0; i < goals.getLength(); i++) {
			Element goal = (Element) goals.item(i);
			String goalID = goal.getAttribute("id");
			// String requester = goal.getAttribute("requester");
			result.addObject(goalID, "t_goal");
			
			String max_sat = goal.getAttribute("max_satisfaction");
			if (max_sat != null && max_sat.length() > 0)
				result.addFact(String.format("(= (max_satisfaction_degree %s) %s)", goalID, max_sat));
			String g = goal.getAttribute("goal");
			
			if ("yes".equalsIgnoreCase(g))
				result.addGoal(goalID);
			
			// if (requester.length() > 0)
			// result.addFact("requests", requester, goalID);
			
			NodeList decompositions = goal.getElementsByTagName("decomposition");
			for (int j = 0; j < decompositions.getLength(); j++) {
				Element de = (Element) decompositions.item(j);
				String[] subgoals = de.getAttribute("subgoals").split(",");
				PddlPredicate p = result.addFact(de.getAttribute("type").toLowerCase() + "_subgoal" + subgoals.length, goalID);
				for (String sg : subgoals)
					p.getArguments().add(sg.trim());
			}
		}
		
		// generate actors
		NodeList actors = (NodeList) xpath.evaluate("//fact/actors/actor", config.Root, XPathConstants.NODESET);
		for (int i = 0; i < actors.getLength(); i++) {
			Element actor = (Element) actors.item(i);
			
			if ("1".equalsIgnoreCase(actor.getAttribute("disabled")))
				continue;
			
			String actorID = actor.getAttribute("id");
			result.addObject(actorID, "t_actor");
			
			String max_job = actor.getAttribute("max_jobs");
			if (max_job != null && max_job.length() > 0)
				result.addFact(String.format("(= (max_job_at_hand %s) %s)", actorID, max_job));
			
			String max_load = actor.getAttribute("max_work_load");
			if (max_load != null && max_load.length() > 0)
				result.addFact(String.format("(= (max_work_load %s) %s)", actorID, max_load));
			
			NodeList provides = actor.getElementsByTagName("can_provide"); // (NodeList)
																			// xpath.evaluate("can_provide",
																			// actor,
																			// XPathConstants.NODESET);
			String requestGoals = config.evalXPath("request/@goals", actor);
			if (requestGoals.length() > 0)
				for (String g : requestGoals.split(",")) {
					result.addFact("requests", actorID, g);
				}
			
			for (int j = 0; j < provides.getLength(); j++) {
				Element provide = (Element) provides.item(j);
				String goalID = provide.getAttribute("goal-id");
				String sat = provide.getAttribute("satisfaction");
				String eff = provide.getAttribute("effort");
				String time = provide.getAttribute("time");
				
				result.addFact("can_provide", actorID, goalID);
				result.addFact(String.format("(= (satisfaction_ability %s %s) %s)", actorID, goalID, sat));
				result.addFact(String.format("(= (work_effort %s %s) %s)", actorID, goalID, eff));
				result.addFact(String.format("(= (time_effort %s %s) %s)", actorID, goalID, time));
			}
		}
		return result;
	}
}
